package reflect;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 利用反射机制实例化对象
 * 步骤:
 *      1：加载要实例化对象的类的类对象
 *      2：直接通过类对象的方法newInstance()实例化
 * */
public class ReflectInstanceObject {
    public static void main(String[] args) throws ClassNotFoundException,
            InstantiationException, IllegalAccessException, InvocationTargetException,
            NoSuchMethodException {
        Object obj = createInstance("reflect.Person");
        System.out.println(obj);

        obj = createInstance("java.util.Date");     // 日期类，其无参构造器默认获取当前系统时间
        System.out.println(obj);

        obj = createInstance2("reflect.Person",
                new Class[]{String.class, int.class}, new Object[]{"晓晓", 22});
        System.out.println(obj);

        demo();
    }

    /** 
     * 通过无参构造器实例化对象
     * @param className     类名（全名，包含报名）
     * @return              返回所创建的对象
     * */
    public static Object createInstance(String className) throws InstantiationException,
            IllegalAccessException, ClassNotFoundException {
        Class<?> c = Class.forName(className);
        // newInstance()方法会调用类对象所表示的类的【公开的无参构造器】实例化
        Object obj = c.newInstance();
        return obj;
    }

    /** 
     * 通过有参构造器实例化对象 
     * @param className         类名（全名，包含报名）
     * @param parameterTypes    构造器参数类型
     * @param parameters        创建实例所需要的类参数
     * @return                  返回所创建的对象
     * */
    public static Object createInstance2(String className, Class<?>[] parameterTypes, Object[] parameters) throws ClassNotFoundException,
            NoSuchMethodException, InvocationTargetException, InstantiationException,
            IllegalAccessException {
        Class<?> c = Class.forName(className);
//        Constructor constructor = c.getConstructor();       // 通过类对象获取无参构造器
        Constructor<?> constructor = c.getConstructor(parameterTypes); // 获取有参构造器
//        Object obj = constructor.newInstance("晚风", 21);     // 创建实例
        Object obj = constructor.newInstance(parameters);     // 创建实例
        return obj;
    }

    /** 通过反射机制调用对象的方法 */
    private static void demo() throws ClassNotFoundException, InvocationTargetException,
            NoSuchMethodException, InstantiationException, IllegalAccessException {
        Class<?> c = Class.forName("reflect.Person");
        Constructor<?> constructor = c.getConstructor(String.class, int.class); // 获取有参构造器
        Object obj = constructor.newInstance("晓晓", 22);     // 创建实例
        String methodName = "sayHello";
        Method method = c.getMethod(methodName);
        method.invoke(obj);
    }
}
